package com.tianhai.db;

import java.io.File;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * TransactionManager完整测试
 */
public class TransactionManagerTest {
    
    public static void main(String[] args) {
        System.out.println("========================================");
        System.out.println("      TransactionManager 事务管理器测试");
        System.out.println("========================================\n");
        
        String walFilePath = "txn_test.wal";
        int totalTests = 0;
        int passedTests = 0;
        
        // 清理旧文件
        new File(walFilePath).delete();
        
        // 测试1: 开始和提交事务
        System.out.println("【测试1】开始和提交事务");
        try {
            TransactionManager txnManager = new TransactionManager(walFilePath);
            
            long txnId = txnManager.beginTransaction();
            boolean isActive = txnManager.isTransactionActive(txnId);
            txnManager.commitTransaction(txnId);
            boolean isActiveAfterCommit = txnManager.isTransactionActive(txnId);
            
            if (isActive && !isActiveAfterCommit) {
                System.out.println("✓ 事务开始和提交成功");
                System.out.println("  事务ID: " + txnId);
                passedTests++;
            } else {
                System.out.println("✗ 事务状态异常");
            }
            
            txnManager.close();
        } catch (Exception e) {
            System.out.println("✗ 异常: " + e.getMessage());
            e.printStackTrace();
        }
        totalTests++;
        System.out.println();
        
        // 测试2: 开始和回滚事务
        System.out.println("【测试2】开始和回滚事务");
        try {
            new File(walFilePath).delete();
            TransactionManager txnManager = new TransactionManager(walFilePath);
            
            long txnId = txnManager.beginTransaction();
            txnManager.rollbackTransaction(txnId);
            boolean isActive = txnManager.isTransactionActive(txnId);
            
            if (!isActive) {
                System.out.println("✓ 事务回滚成功");
                passedTests++;
            } else {
                System.out.println("✗ 回滚后事务仍活跃");
            }
            
            txnManager.close();
        } catch (Exception e) {
            System.out.println("✗ 异常: " + e.getMessage());
        }
        totalTests++;
        System.out.println();
        
        // 测试3: INSERT操作（自动获取锁和记录日志）
        System.out.println("【测试3】INSERT操作 - 自动获取排他锁和记录日志");
        try {
            new File(walFilePath).delete();
            TransactionManager txnManager = new TransactionManager(walFilePath);
            
            long txnId = txnManager.beginTransaction();
            txnManager.executeInsert(txnId, "users", "{id:1, name:'张三'}");
            txnManager.executeInsert(txnId, "users", "{id:2, name:'李四'}");
            txnManager.commitTransaction(txnId);
            
            // 恢复验证
            txnManager.close();
            txnManager = new TransactionManager(walFilePath);
            List<WAL.Transaction> recovered = txnManager.recover();
            
            if (recovered.size() == 1 && recovered.get(0).logRecords.size() == 4) {
                System.out.println("✓ INSERT操作成功，日志记录正确");
                System.out.println("  恢复的日志数: " + recovered.get(0).logRecords.size());
                passedTests++;
            } else {
                System.out.println("✗ INSERT操作或日志记录异常");
            }
            
            txnManager.close();
        } catch (Exception e) {
            System.out.println("✗ 异常: " + e.getMessage());
            e.printStackTrace();
        }
        totalTests++;
        System.out.println();
        
        // 测试4: UPDATE操作
        System.out.println("【测试4】UPDATE操作 - 自动获取排他锁和记录日志");
        try {
            new File(walFilePath).delete();
            TransactionManager txnManager = new TransactionManager(walFilePath);
            
            long txnId = txnManager.beginTransaction();
            txnManager.executeUpdate(txnId, "users", "{id:1, age:30}");
            txnManager.commitTransaction(txnId);
            
            txnManager.close();
            txnManager = new TransactionManager(walFilePath);
            List<WAL.Transaction> recovered = txnManager.recover();
            
            if (recovered.size() == 1) {
                System.out.println("✓ UPDATE操作成功");
                passedTests++;
            } else {
                System.out.println("✗ UPDATE操作异常");
            }
            
            txnManager.close();
        } catch (Exception e) {
            System.out.println("✗ 异常: " + e.getMessage());
        }
        totalTests++;
        System.out.println();
        
        // 测试5: DELETE操作
        System.out.println("【测试5】DELETE操作 - 自动获取排他锁和记录日志");
        try {
            new File(walFilePath).delete();
            TransactionManager txnManager = new TransactionManager(walFilePath);
            
            long txnId = txnManager.beginTransaction();
            txnManager.executeDelete(txnId, "users", "{id:1}");
            txnManager.commitTransaction(txnId);
            
            txnManager.close();
            txnManager = new TransactionManager(walFilePath);
            List<WAL.Transaction> recovered = txnManager.recover();
            
            if (recovered.size() == 1) {
                System.out.println("✓ DELETE操作成功");
                passedTests++;
            } else {
                System.out.println("✗ DELETE操作异常");
            }
            
            txnManager.close();
        } catch (Exception e) {
            System.out.println("✗ 异常: " + e.getMessage());
        }
        totalTests++;
        System.out.println();
        
        // 测试6: SELECT操作（读已提交隔离级别）
        System.out.println("【测试6】SELECT操作 - 读已提交隔离级别");
        try {
            new File(walFilePath).delete();
            TransactionManager txnManager = new TransactionManager(walFilePath);
            
            long txnId = txnManager.beginTransaction();
            txnManager.executeSelect(txnId, "users");
            // 读已提交：SELECT后共享锁应立即释放
            txnManager.commitTransaction(txnId);
            
            System.out.println("✓ SELECT操作成功（读已提交：锁立即释放）");
            passedTests++;
            
            txnManager.close();
        } catch (Exception e) {
            System.out.println("✗ 异常: " + e.getMessage());
        }
        totalTests++;
        System.out.println();
        
        // 测试7: 多操作事务
        System.out.println("【测试7】多操作事务 - INSERT/UPDATE/DELETE混合");
        try {
            new File(walFilePath).delete();
            TransactionManager txnManager = new TransactionManager(walFilePath);
            
            long txnId = txnManager.beginTransaction();
            txnManager.executeInsert(txnId, "users", "{id:1}");
            txnManager.executeUpdate(txnId, "users", "{id:1, age:25}");
            txnManager.executeSelect(txnId, "users");
            txnManager.executeDelete(txnId, "orders", "{id:100}");
            txnManager.commitTransaction(txnId);
            
            txnManager.close();
            txnManager = new TransactionManager(walFilePath);
            List<WAL.Transaction> recovered = txnManager.recover();
            
            if (recovered.size() == 1 && recovered.get(0).logRecords.size() == 5) {
                System.out.println("✓ 多操作事务成功");
                System.out.println("  操作数: " + (recovered.get(0).logRecords.size() - 2));
                passedTests++;
            } else {
                System.out.println("✗ 多操作事务异常");
            }
            
            txnManager.close();
        } catch (Exception e) {
            System.out.println("✗ 异常: " + e.getMessage());
        }
        totalTests++;
        System.out.println();
        
        // 测试8: 回滚事务不恢复
        System.out.println("【测试8】回滚事务不恢复");
        try {
            new File(walFilePath).delete();
            TransactionManager txnManager = new TransactionManager(walFilePath);
            
            // 事务1：提交
            long txn1 = txnManager.beginTransaction();
            txnManager.executeInsert(txn1, "users", "{id:1}");
            txnManager.commitTransaction(txn1);
            
            // 事务2：回滚
            long txn2 = txnManager.beginTransaction();
            txnManager.executeInsert(txn2, "users", "{id:2}");
            txnManager.rollbackTransaction(txn2);
            
            txnManager.close();
            txnManager = new TransactionManager(walFilePath);
            List<WAL.Transaction> recovered = txnManager.recover();
            
            if (recovered.size() == 1 && recovered.get(0).txnId == txn1) {
                System.out.println("✓ 只恢复已提交事务，回滚事务不恢复");
                passedTests++;
            } else {
                System.out.println("✗ 回滚事务处理异常");
            }
            
            txnManager.close();
        } catch (Exception e) {
            System.out.println("✗ 异常: " + e.getMessage());
        }
        totalTests++;
        System.out.println();
        
        // 测试9: 并发事务（无冲突）
        System.out.println("【测试9】并发事务 - 不同资源无冲突");
        try {
            new File(walFilePath).delete();
            TransactionManager txnManager = new TransactionManager(walFilePath);
            
            CountDownLatch latch = new CountDownLatch(3);
            AtomicInteger successCount = new AtomicInteger(0);
            
            ExecutorService executor = Executors.newFixedThreadPool(3);
            
            // 3个并发事务操作不同表
            for (int i = 0; i < 3; i++) {
                final String tableName = "table" + i;
                executor.submit(() -> {
                    try {
                        long txnId = txnManager.beginTransaction();
                        txnManager.executeInsert(txnId, tableName, "{id:1}");
                        txnManager.commitTransaction(txnId);
                        successCount.incrementAndGet();
                    } catch (Exception e) {
                        e.printStackTrace();
                    } finally {
                        latch.countDown();
                    }
                });
            }
            
            latch.await(10, TimeUnit.SECONDS);
            executor.shutdown();
            
            if (successCount.get() == 3) {
                System.out.println("✓ 并发事务成功（操作不同资源）");
                System.out.println("  成功事务数: " + successCount.get() + "/3");
                passedTests++;
            } else {
                System.out.println("✗ 并发事务失败");
            }
            
            txnManager.close();
        } catch (Exception e) {
            System.out.println("✗ 异常: " + e.getMessage());
            e.printStackTrace();
        }
        totalTests++;
        System.out.println();
        
        // 测试10: 并发事务（有冲突）
        System.out.println("【测试10】并发事务 - 同一资源有冲突");
        try {
            new File(walFilePath).delete();
            TransactionManager txnManager = new TransactionManager(walFilePath);
            
            CountDownLatch latch = new CountDownLatch(5);
            AtomicInteger successCount = new AtomicInteger(0);
            AtomicInteger timeoutCount = new AtomicInteger(0);
            
            ExecutorService executor = Executors.newFixedThreadPool(5);
            
            // 5个并发事务竞争同一个表
            for (int i = 0; i < 5; i++) {
                final int id = i;
                executor.submit(() -> {
                    try {
                        long txnId = txnManager.beginTransaction();
                        txnManager.executeInsert(txnId, "users", "{id:" + id + "}");
                        Thread.sleep(50); // 持有锁一段时间
                        txnManager.commitTransaction(txnId);
                        successCount.incrementAndGet();
                    } catch (RuntimeException e) {
                        if (e.getMessage().contains("超时")) {
                            timeoutCount.incrementAndGet();
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    } finally {
                        latch.countDown();
                    }
                });
            }
            
            latch.await(30, TimeUnit.SECONDS);
            executor.shutdown();
            
            int total = successCount.get() + timeoutCount.get();
            if (total == 5 && successCount.get() > 0) {
                System.out.println("✓ 并发冲突处理正确");
                System.out.println("  成功: " + successCount.get() + ", 超时: " + timeoutCount.get());
                passedTests++;
            } else {
                System.out.println("✗ 并发冲突处理异常");
            }
            
            txnManager.close();
        } catch (Exception e) {
            System.out.println("✗ 异常: " + e.getMessage());
            e.printStackTrace();
        }
        totalTests++;
        System.out.println();
        
        // 测试11: 崩溃恢复
        System.out.println("【测试11】崩溃恢复 - 从WAL恢复已提交事务");
        try {
            new File(walFilePath).delete();
            TransactionManager txnManager = new TransactionManager(walFilePath);
            
            // 执行多个事务
            long txn1 = txnManager.beginTransaction();
            txnManager.executeInsert(txn1, "users", "{id:1}");
            txnManager.commitTransaction(txn1);
            
            long txn2 = txnManager.beginTransaction();
            txnManager.executeInsert(txn2, "orders", "{id:100}");
            txnManager.commitTransaction(txn2);
            
            txnManager.close();
            
            // 模拟崩溃重启，恢复
            txnManager = new TransactionManager(walFilePath);
            List<WAL.Transaction> recovered = txnManager.recover();
            
            if (recovered.size() == 2) {
                System.out.println("✓ 崩溃恢复成功");
                System.out.println("  恢复事务数: " + recovered.size());
                for (WAL.Transaction txn : recovered) {
                    System.out.println("    " + txn);
                }
                passedTests++;
            } else {
                System.out.println("✗ 崩溃恢复异常");
            }
            
            txnManager.close();
        } catch (Exception e) {
            System.out.println("✗ 异常: " + e.getMessage());
        }
        totalTests++;
        System.out.println();
        
        // 测试12: 活跃事务计数
        System.out.println("【测试12】活跃事务计数");
        try {
            new File(walFilePath).delete();
            TransactionManager txnManager = new TransactionManager(walFilePath);
            
            long txn1 = txnManager.beginTransaction();
            long txn2 = txnManager.beginTransaction();
            long txn3 = txnManager.beginTransaction();
            
            int count1 = txnManager.getActiveTransactionCount();
            
            txnManager.commitTransaction(txn1);
            int count2 = txnManager.getActiveTransactionCount();
            
            txnManager.rollbackTransaction(txn2);
            txnManager.commitTransaction(txn3);
            int count3 = txnManager.getActiveTransactionCount();
            
            if (count1 == 3 && count2 == 2 && count3 == 0) {
                System.out.println("✓ 活跃事务计数正确");
                System.out.println("  开始3个 -> 提交1个后2个 -> 全部结束0个");
                passedTests++;
            } else {
                System.out.println("✗ 活跃事务计数异常");
            }
            
            txnManager.close();
        } catch (Exception e) {
            System.out.println("✗ 异常: " + e.getMessage());
        }
        totalTests++;
        System.out.println();
        
        // 清理测试文件
        new File(walFilePath).delete();
        
        // 测试结果汇总
        System.out.println("========================================");
        System.out.println("           测试结果汇总");
        System.out.println("========================================");
        System.out.println("总测试数: " + totalTests);
        System.out.println("通过数: " + passedTests);
        System.out.println("失败数: " + (totalTests - passedTests));
        System.out.println("通过率: " + String.format("%.1f%%", passedTests * 100.0 / totalTests));
        System.out.println("----------------------------------------");
        
        if (passedTests == totalTests) {
            System.out.println("✓✓✓ 所有测试通过！");
        } else {
            System.out.println("✗✗✗ 部分测试失败");
        }
        System.out.println("========================================\n");
    }
}
